/*-------------------------------------------------------------------------*/
/* The following function demonstrates the use of optimized color          */
/* space conversion routine "ycbcr422pl_to_rgb565". It accepts             */
/* pointers to even and odd fields data for (YCRCB) and converts           */
/* data to RGB565 format. This function has been modified to drop          */
/* one field of data, and scale the other field by a factor of 2           */
/* horizontally. Thus this function prepares a 320x240 4:2:0  Y,           */
/* Cr, Cb data in memory. The Cr and Cb data are each 160x240.             */
/*-------------------------------------------------------------------------*/   

/*-------------------------------------------------------------------------*/
/* Include header files for image processing and ImageDataManager          */
/*-------------------------------------------------------------------------*/

#include "img_proc.h"
#include "dstr_2d.h"
#include "csl_dat.h"
#include "csl_irq.h"

/*-------------------------------------------------------------------------*/
/* if DEBUG flag is turned ON, then use the LOG Object trace               */
/*-------------------------------------------------------------------------*/

#ifdef DEBUG
#include <std.h>
#include <log.h>
extern LOG_Obj trace;
#endif 

/*-------------------------------------------------------------------------*/
/* The function color_convert repeatedly calls "ycbcr422pl_to_rgb565"      */
/* to perform color space conversion from 4:2:2 YCrCb format to RGB565     */
/* The function has the following prototype:                               */
/*                                                                         */
/* void color_convert                                                      */
/*(                                                                        */  
/*  IMAGE *in_image_luma_ev, IMAGE *in_image_cr_ev, IMAGE *in_image_cb_ev, */
/*  IMAGE *in_image_luma_od, IMAGE *in_image_cr_od, IMAGE *in_image_cb_od, */
/*  IMAGE *out_image,        SCRATCH_PAD  *scratch_pad)                    */
/*                                                                         */
/* where:                                                                  */
/*                                                                         */
/* in_image_luma_ev: IMAGE pointer to even Y or luma field                 */
/* in_image_cr_ev:   IMAGE pointer to even CR   field                      */
/* in_image_cb_ev:   IMAGE pointer to even CB   field                      */
/* in_image_luma_od: IMAGE pointer to odd  Y or luma field                 */
/* in_image_cr_od:   IMAGE pointer to odd  CR   field                      */
/* in_image_cb_od:   IMAGE pointer to odd  CB   field                      */
/* out_image:        IMAGE pointer to output    image                      */
/* scratch_pad:      SCRATCH_PAD pointer to temporary external and inter-  */
/*                   nal scratch buffers.                                  */
/*                                                                         */
/* This function allows the user to work on multiple lines, (in this case  */
/* 2). The results of working on all the even lines first followed by the  */
/* odd lines next are merged by using DMA's with appropriate offsets. The  */
/* pixel cache on the Imaging daughter card supports bursting through the  */
/* lines in the even or odd field better than accessing the lines of the   */
/* even and odd field back to back.                                        */
/*-------------------------------------------------------------------------*/


void color_convert
(
   IMAGE *in_image_luma_ev, IMAGE *in_image_cr_ev, IMAGE *in_image_cb_ev,
   IMAGE *in_image_luma_od, IMAGE *in_image_cr_od, IMAGE *in_image_cb_od,
   IMAGE *out_image,        SCRATCH_PAD  *scratch_pad)
{  

    /*---------------------------------------------------------------------*/
    /* "int_mem" is start of internal meory. The # rows and # cols for the */
    /* luma even field and the output image are also initialized at this   */
    /* point.                                                              */
    /*---------------------------------------------------------------------*/
    
    char *int_mem = scratch_pad->int_data;
    char *ext_mem = scratch_pad->ext_data;
   
    int  rows     = in_image_luma_ev->img_rows;
    int  cols     = in_image_luma_ev->img_cols;
//    int  out_rows = out_image->img_rows;
//    int  out_cols = out_image->img_cols;
    
    int     i;// j;
    dstr_t  i_luma_ev, i_cr_ev, i_cb_ev;
   
    
    int err_code;
    int num_lines = 1; 
    unsigned int id;
    
    unsigned char *ext_Y, *ext_CR, *ext_CB;
    
    /*---------------------------------------------------------------------*/
    /* Internal memory allocation is done to scale with the image size. In */
    /* this file since both the even and odd fields are processed simulta- */
    /* neously, six input streams and one output stream are required to    */
    /* handle the processing. The data for these streams needs to be bro-  */
    /* ught into internal memory. The internal memory is partitioned as    */
    /* follows for this purpose:                                           */
    /*                                                                     */
    /* Even luma data: int_luma_ev      Double buffering width : 2 * cols  */
    /* Even Cr   data: int_cr_ev        Double buffering width : cols      */
    /* Even Cb   data: int_cb_ev        Double buffering width : cols      */
    /*                                                                     */
    /* out_data: Internal memory to hold processed RGB data                */
    /* Double buffering width: 2 * out_cols                                */ 
    /*                                                                     */
    /* Note that this method uses reduced memory as compared to having to  */
    /* work with both even and odd fields at the same time.                */
    /*---------------------------------------------------------------------*/
    
    char *int_luma_ev = int_mem;
    char *int_cr_ev   = int_mem  + (2 * cols * num_lines);
    char *int_cb_ev   = int_mem  + (3 * cols * num_lines);
//    char *out_data    = int_mem  + (4 * cols * num_lines); 
    
   
    
   
    /*---------------------------------------------------------------------*/
    /* These pointers will be assigned to internal memory as and when they */
    /* become available from DMA                                           */
    /*---------------------------------------------------------------------*/
    
    unsigned char *Y, *Cr, *Cb; //*RGB;
        
   /*---------------------------------------------------------------------*/
   /* Coefficients to be used for Color space conversion                  */
   /*---------------------------------------------------------------------*/

//    short coeffs[] = { 0x2543, 0x3313, -0x0C8A, -0x1A04, 0x408D }; 
    
    
    /*--------------------------------------------------------------------*/
    /* Use scratch pad memory. These are the locations into which the     */
    /* modified Y, Cr, Cb data are written to. The scaling function will  */
    /* be passed on these locations for use.                              */
    /*--------------------------------------------------------------------*/
    
    ext_Y  = (unsigned char *) ext_mem;
    ext_CR = ext_Y   + (720 * 240);
    ext_CB = ext_CR  + (360 * 240);
    
   /*---------------------------------------------------------------------*/
   /* Initialize sream for luma data for even field, to bring in 1 line   */
   /* at a time                                                           */
   /*---------------------------------------------------------------------*/
    
    err_code = dstr_open( &i_luma_ev,
                          in_image_luma_ev->img_data,
                          2 * rows * cols,
                          int_luma_ev,
                          2 * cols * num_lines,
                          cols,
                          num_lines,
                          2 * cols,
                          1,
                          DSTR_INPUT);
   
   #ifdef DEBUG                       
   if (err_code)
   {
       LOG_printf(&trace, "error opening luma stream %d \n",
       err_code);
   }
   #else
   (void)(err_code); 
   #endif 
   
      
   /*---------------------------------------------------------------------*/
   /* Initialize stream for Cr  data for even field, to bring in 1 line   */
   /* at a time                                                           */
   /*---------------------------------------------------------------------*/
   
   err_code = dstr_open( &i_cr_ev,
                         in_image_cr_ev->img_data,
                         (2 * rows * cols),
                         int_cr_ev,
                         cols * num_lines,
                         cols >> 1,
                         num_lines,
                         cols,
                         1,
                         DSTR_INPUT);
   
   #ifdef DEBUG                      
   if (err_code)
   {
       LOG_printf(&trace, "error opening cr stream %d \n",
       err_code);
   } 
   #else
   (void)(err_code);
   #endif 
   
         
   /*---------------------------------------------------------------------*/
   /* Initialize stream for Cb  data for even field, to bring in 1 line   */
   /* at a time                                                           */
   /*---------------------------------------------------------------------*/
   
   err_code = dstr_open( &i_cb_ev,
                         in_image_cb_ev->img_data,
                         (2 * rows * cols),
                         int_cb_ev,
                         cols * num_lines,
                         cols >> 1,
                         num_lines,
                         cols,
                         1,
                         DSTR_INPUT
                       );
   
   #ifdef DEBUG                      
   if (err_code)
   {
       LOG_printf(&trace, "error opening cb stream %d \n",
       err_code);
   }
   #else
   (void)(err_code); 
   #endif 
   
   /*-------------------------------------------------------------------*/
   /* The previous code performed color space conversion. This is done  */
   /* from within the scaling function and hence the output stream is   */
   /* commented out.                                                    */
   /*-------------------------------------------------------------------*/
   
   
   

   
   /*--------------------------------------------------------------------*/
   /* For all rows of the even field obtain luma Y, Cr and               */
   /* Cb data and call optimized color space conversion routine. Commit  */
   /* results to display buffer. Update luma Y, Cr and Cb with pointers  */
   /* for odd fields and commit results to external memory. In this ex-  */
   /* ample 1 line of the image from the even field and 1 line of the    */
   /* image from the odd field are processed back to back.               */
   /*--------------------------------------------------------------------*/
   
   for ( i = 0; i < rows; i++)
   {
       /*----------------------------------------------------------------*/
       /* Obtain Y, Cr, Cb pointers for even/odd field. The call to put  */
       /* routine returns information on where the output results are to */
       /* be written. These calls need to be to the 2D routines as mul-  */
       /* tiple lines need to be read and written at the same time.      */
       /*----------------------------------------------------------------*/
       
       Y  = (unsigned char *) dstr_get_2D(&i_luma_ev);
       Cr = (unsigned char *) dstr_get_2D(&i_cr_ev);
       Cb = (unsigned char *) dstr_get_2D(&i_cb_ev);
       
                    
       
       if (i) DAT_wait(id);
       
       DAT_copy(Y,       ext_Y  + (i * 720),  720);
       DAT_copy(Cr,      ext_CR + (i * 360),  360);
       id = DAT_copy(Cb, ext_CB + (i * 360),  360);
                       
   } 
   
   
   /*--------------------------------------------------------------------*/
   /* Commit last set of results to output buffer for both even/odd      */
   /* field.                                                             */
   /*--------------------------------------------------------------------*/
   
   DAT_wait(id);
   
   
    
   
    
   /*-------------------------------------------------------------------*/
   /* Close streams for Y, Cr and Cb                                    */
   /*-------------------------------------------------------------------*/
  
   #if 0
   dstr_close(&i_luma_ev);
   dstr_close(&i_cr_ev);
   dstr_close(&i_cb_ev); 
   #endif
   
}   
                         
                       
